import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from wordcloud import WordCloud
import tkinter as tk
from tkinter import ttk, messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import os
import warnings
warnings.filterwarnings('ignore')

class MovieDataProcessor:
    def __init__(self, file_path):
        """初始化数据处理器"""
        self.file_path = file_path
        self.data = None
        self.load_data()
    
    def load_data(self):
        """加载数据并进行基础处理"""
        try:
            self.data = pd.read_csv(self.file_path)
            # 处理缺失值
            self.data = self.data.fillna({
                'budget': self.data['budget'].median(),
                'gross': self.data['gross'].median(),
                'imdb_score': self.data['imdb_score'].mean()
            })
        except Exception as e:
            raise Exception(f"数据加载失败: {str(e)}")
    
    def get_basic_stats(self):
        """获取基本统计信息"""
        return {
            '电影总数': len(self.data),
            '平均预算': self.data['budget'].mean(),
            '平均票房': self.data['gross'].mean(),
            '平均评分': self.data['imdb_score'].mean()
        }
    
    def get_genre_distribution(self):
        """获取电影类型分布"""
        genres = self.data['genres'].str.split('|').explode()
        return genres.value_counts()
    
    def get_year_trend(self):
        """获取年度趋势"""
        return self.data.groupby('title_year')['imdb_score'].mean()

class MovieVisualizer:
    def __init__(self, data_processor):
        """初始化可视化器"""
        self.data_processor = data_processor
        self.data = data_processor.data
    
    def plot_budget_vs_gross(self):
        """绘制预算vs票房散点图"""
        fig = px.scatter(self.data, x='budget', y='gross',
                        title='电影预算与票房关系',
                        labels={'budget': '预算', 'gross': '票房'})
        return fig
    
    def plot_genre_distribution(self):
        """绘制电影类型分布饼图"""
        genre_dist = self.data_processor.get_genre_distribution()
        fig = px.pie(values=genre_dist.values, 
                    names=genre_dist.index,
                    title='电影类型分布')
        return fig
    
    def plot_score_trend(self):
        """绘制评分趋势折线图"""
        year_trend = self.data_processor.get_year_trend()
        fig = px.line(x=year_trend.index, y=year_trend.values,
                     title='电影评分年度趋势',
                     labels={'x': '年份', 'y': '平均评分'})
        return fig
    
    def create_wordcloud(self):
        """创建电影标题词云"""
        text = ' '.join(self.data['movie_title'].astype(str))
        wordcloud = WordCloud(width=800, height=400,
                            background_color='white',
                            font_path='simhei.ttf').generate(text)
        return wordcloud
    
    def plot_director_analysis(self):
        """分析导演作品数量和平均评分"""
        director_stats = self.data.groupby('director_name').agg({
            'movie_title': 'count',
            'imdb_score': 'mean'
        }).sort_values('movie_title', ascending=False).head(10)
        
        fig = go.Figure()
        fig.add_trace(go.Bar(
            x=director_stats.index,
            y=director_stats['movie_title'],
            name='电影数量'
        ))
        fig.add_trace(go.Scatter(
            x=director_stats.index,
            y=director_stats['imdb_score'],
            name='平均评分',
            yaxis='y2'
        ))
        
        fig.update_layout(
            title='Top 10导演作品数量与平均评分',
            yaxis=dict(title='电影数量'),
            yaxis2=dict(title='平均评分', overlaying='y', side='right'),
            showlegend=True
        )
        return fig
    
    def plot_actor_network(self):
        """分析演员合作网络"""
        # 获取前20部评分最高的电影
        top_movies = self.data.nlargest(20, 'imdb_score')
        # 提取演员列表
        actors = top_movies['actor_1_name'].tolist() + \
                top_movies['actor_2_name'].tolist() + \
                top_movies['actor_3_name'].tolist()
        
        # 统计演员出现频率
        actor_counts = pd.Series(actors).value_counts().head(10)
        
        fig = go.Figure(data=[go.Bar(
            x=actor_counts.index,
            y=actor_counts.values,
            text=actor_counts.values,
            textposition='auto',
        )])
        
        fig.update_layout(
            title='Top 10最受欢迎演员',
            xaxis_title='演员',
            yaxis_title='出演电影数量'
        )
        return fig
    
    def plot_budget_distribution(self):
        """分析预算分布"""
        fig = go.Figure()
        fig.add_trace(go.Histogram(
            x=self.data['budget'],
            nbinsx=50,
            name='预算分布'
        ))
        
        fig.update_layout(
            title='电影预算分布',
            xaxis_title='预算',
            yaxis_title='电影数量',
            showlegend=True
        )
        return fig
    
    def plot_correlation_matrix(self):
        """分析数值特征之间的相关性"""
        numeric_cols = ['budget', 'gross', 'imdb_score', 'duration', 'num_voted_users']
        corr_matrix = self.data[numeric_cols].corr()
        
        fig = go.Figure(data=go.Heatmap(
            z=corr_matrix,
            x=corr_matrix.columns,
            y=corr_matrix.columns,
            colorscale='RdBu'
        ))
        
        fig.update_layout(
            title='特征相关性热力图',
            height=600,
            width=600
        )
        return fig

class MovieAnalysisGUI:
    def __init__(self):
        """初始化GUI界面"""
        self.root = tk.Tk()
        self.root.title("电影数据分析系统")
        self.root.geometry("1200x800")
        
        try:
            self.processor = MovieDataProcessor('movie_metadata/movie_metadata.csv')
            self.visualizer = MovieVisualizer(self.processor)
        except Exception as e:
            messagebox.showerror("错误", f"数据加载失败: {str(e)}")
            self.root.destroy()
            return
        
        self.create_widgets()
    
    def create_widgets(self):
        """创建GUI组件"""
        # 创建左侧控制面板
        control_frame = ttk.LabelFrame(self.root, text="分析选项")
        control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5)
        
        # 添加按钮
        buttons = [
            ("预算vs票房分析", self.show_budget_gross),
            ("电影类型分布", self.show_genre_dist),
            ("评分趋势分析", self.show_score_trend),
            ("电影标题词云", self.show_wordcloud),
            ("导演分析", self.show_director_analysis),
            ("演员分析", self.show_actor_network),
            ("预算分布", self.show_budget_distribution),
            ("相关性分析", self.show_correlation_matrix)
        ]
        
        for text, command in buttons:
            ttk.Button(control_frame, text=text, command=command).pack(pady=5)
        
        # 创建右侧显示区域
        self.display_frame = ttk.LabelFrame(self.root, text="分析结果")
        self.display_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建文本显示区域
        self.text_widget = tk.Text(self.display_frame, wrap=tk.WORD)
        self.text_widget.pack(fill=tk.BOTH, expand=True)
    
    def show_budget_gross(self):
        """显示预算vs票房分析"""
        self.clear_display()
        fig = self.visualizer.plot_budget_vs_gross()
        self.show_plotly_figure(fig)
    
    def show_genre_dist(self):
        """显示电影类型分布"""
        self.clear_display()
        fig = self.visualizer.plot_genre_distribution()
        self.show_plotly_figure(fig)
    
    def show_score_trend(self):
        """显示评分趋势"""
        self.clear_display()
        fig = self.visualizer.plot_score_trend()
        self.show_plotly_figure(fig)
    
    def show_wordcloud(self):
        """显示词云"""
        self.clear_display()
        wordcloud = self.visualizer.create_wordcloud()
        plt.figure(figsize=(10, 5))
        plt.imshow(wordcloud, interpolation='bilinear')
        plt.axis('off')
        self.show_matplotlib_figure()
    
    def show_plotly_figure(self, fig):
        """在GUI中显示Plotly图形"""
        self.clear_display()
        
        # 将Plotly图形保存为临时HTML文件
        temp_file = "temp_plot.html"
        fig.write_html(temp_file)
        
        # 在文本组件中显示HTML内容
        with open(temp_file, 'r', encoding='utf-8') as f:
            html_content = f.read()
        
        self.text_widget.delete(1.0, tk.END)
        self.text_widget.insert(tk.END, "图表已生成，请在浏览器中查看。\n")
        self.text_widget.insert(tk.END, f"文件位置: {os.path.abspath(temp_file)}\n")
        
        # 自动打开浏览器显示图表
        import webbrowser
        webbrowser.open(temp_file)
    
    def show_matplotlib_figure(self):
        """显示Matplotlib图形"""
        canvas = FigureCanvasTkAgg(plt.gcf(), master=self.display_frame)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
    
    def show_director_analysis(self):
        """显示导演分析"""
        fig = self.visualizer.plot_director_analysis()
        self.show_plotly_figure(fig)
    
    def show_actor_network(self):
        """显示演员分析"""
        fig = self.visualizer.plot_actor_network()
        self.show_plotly_figure(fig)
    
    def show_budget_distribution(self):
        """显示预算分布"""
        fig = self.visualizer.plot_budget_distribution()
        self.show_plotly_figure(fig)
    
    def show_correlation_matrix(self):
        """显示相关性分析"""
        fig = self.visualizer.plot_correlation_matrix()
        self.show_plotly_figure(fig)
    
    def clear_display(self):
        """清除显示区域"""
        self.text_widget.delete(1.0, tk.END)
        for widget in self.display_frame.winfo_children():
            if widget != self.text_widget:
                widget.destroy()
    
    def run(self):
        """运行GUI程序"""
        self.root.mainloop()

if __name__ == "__main__":
    app = MovieAnalysisGUI()
    app.run()
